﻿Imports System.Globalization
Imports Ventrian.PropertyAgent
Imports DotNetNuke.Entities.Modules
Imports Aricie.DNN.Modules.ModuleWorkflows.Business
Imports Aricie.DNN.Modules.ModuleWorkflows
Imports System.Text
Imports System.Data.SqlClient
Imports DotNetNuke.Common.Utilities
Imports DotNetNuke.Entities.Users
Imports DotNetNuke.Entities.Profile

Namespace Aricie.DNN.Services.Url.FriendlyUrl.Providers

    Public Class PropertyAgentUrlRewriter
        Implements IModulesListUrlRewriterProvider
        Implements ICategoryUrlRewriterProvider
        Implements IIsActive


        Private Const glbDesktopModuleName As String = "PropertyAgent"
        Private Const glbCustomFieldPrefix As String = "PACustom"
        Private Const glbAgentProfilePrefix As String = "PAAgentProfile"

        Private Shared _PropertyController As New PropertyController
        Private Shared _PropertyTypeController As New PropertyTypeController
        Private Shared _PropertyValueController As New PropertyValueController
        Private Shared _CustomFieldController As New CustomFieldController
        'Modif CGA 04/05/12
        'Modification du dictionaire _CustomFieldIds pour gérer plusieurs instances PA avec les mêmes custom fields.
        Private Shared _CustomFieldIds As New Dictionary(Of String, List(Of CustomFieldInfo))

        Public Function GetModuleRewrites() As List(Of GroupParamsRewrite) Implements IUrlRewriterProvider.GetRewrites
            Dim toReturn As New List(Of GroupParamsRewrite)
            Dim desc As String = "Display name of the current Property Agent's entity, filtered according to the general parameters"
            toReturn.Add(New GroupParamsRewrite("DisplayName", desc, RewriteType.SubPath, UrlParam.FromSyntax("propertyid")))

            desc = "Display name of the current Property Agent's Type, filtered according to the general parameters"
            Dim groupToAdd As New GroupParamsRewrite("PAType", desc, RewriteType.SubPath, UrlParam.FromSyntax("propertyid"))
            groupToAdd.UrlParams(UrlParam.FromSyntax("propertyid")) = ParamNature.NonExclusive Or ParamNature.Mandatory
            toReturn.Add(groupToAdd)

            desc = "Display name of the Property Agent's Type for the current property type, filtered according to the general parameters"
            groupToAdd = New GroupParamsRewrite("PAPropertyTypes", desc, RewriteType.Any, UrlParam.FromSyntax("propertytypeid"))
            toReturn.Add(groupToAdd)

            'declaring existing custom fields as rewrite groups
            Me.FillCustomFields()

            For Each fieldName As String In _CustomFieldIds.Keys
                '
                desc = _CustomFieldIds(fieldName)(0).CaptionHelp
                Dim toAdd As New GroupParamsRewrite(glbCustomFieldPrefix & fieldName, desc, RewriteType.SubPath, UrlParam.FromSyntax("propertyid"))
                toAdd.UrlParams(UrlParam.FromSyntax("propertyid")) = ParamNature.NonExclusive Or ParamNature.Mandatory
                toReturn.Add(toAdd)
            Next

            For Each propDefinition As ProfilePropertyDefinition In ProfileController.GetPropertyDefinitionsByPortal(NukeHelper.PortalId)
                Dim toAdd As New GroupParamsRewrite(glbAgentProfilePrefix & propDefinition.PropertyName, "", RewriteType.SubPath, UrlParam.FromSyntax("propertyid"))
                toAdd.UrlParams(UrlParam.FromSyntax("propertyid")) = ParamNature.NonExclusive Or ParamNature.Mandatory
                toReturn.Add(toAdd)
            Next

            Return toReturn
        End Function

        'Dans le cas ou le module est encapsulé, il n'est pas possible de retrouver les modules, il doivent donc provenir des parametres
        Public Function GetRewrites(ByVal modulesIds As List(Of Integer)) As System.Collections.Generic.List(Of GroupParamsRewrite) Implements IModulesListUrlRewriterProvider.GetRewrites
            Dim toReturn As New List(Of GroupParamsRewrite)
            Dim desc As String = "Display name of the current Property Agent's entity, filtered according to the general parameters"
            toReturn.Add(New GroupParamsRewrite("DisplayName", desc, RewriteType.SubPath, UrlParam.FromSyntax("propertyid")))

            desc = "Display name of Property Agent's Type for the current property, filtered according to the general parameters"
            Dim groupToAdd As New GroupParamsRewrite("PAType", desc, RewriteType.Any, UrlParam.FromSyntax("propertyid"))
            groupToAdd.UrlParams(UrlParam.FromSyntax("propertyid")) = ParamNature.NonExclusive Or ParamNature.Mandatory

            toReturn.Add(groupToAdd)

            desc = "Display name of the Property Agent's Type for the current property type, filtered according to the general parameters"
            groupToAdd = New GroupParamsRewrite("PAPropertyTypes", desc, RewriteType.Any, UrlParam.FromSyntax("propertytypeid"))
            toReturn.Add(groupToAdd)


            'declaring existing custom fields as rewrite groups
            Me.FillCustomFields(modulesIds)

            For Each fieldName As String In _CustomFieldIds.Keys
                Dim toAdd As New GroupParamsRewrite(glbCustomFieldPrefix & fieldName, desc, RewriteType.SubPath, UrlParam.FromSyntax("propertyid"))
                toAdd.UrlParams(UrlParam.FromSyntax("propertyid")) = ParamNature.NonExclusive Or ParamNature.Mandatory
                toReturn.Add(toAdd)
            Next

            Return toReturn

        End Function


        Private Sub FillCustomFields(Optional ByVal modulesIds As List(Of Integer) = Nothing)
            Dim mDefId As Integer = NukeHelper.GetModuleDefIdByModuleName(glbDesktopModuleName)
            If mDefId <> -1 Then
                Dim modules As ArrayList = Nothing
                Dim customFields As List(Of CustomFieldInfo)

                If modulesIds Is Nothing Then
                    Dim moduleDefFriendlyName As String = NukeHelper.ModuleDefinitionController.GetModuleDefinition(mDefId).FriendlyName
                    modules = NukeHelper.ModuleController.GetModulesByDefinition(NukeHelper.PortalId, moduleDefFriendlyName)


                    For Each propModule As ModuleInfo In modules
                        Try
                            customFields = _CustomFieldController.List(propModule.ModuleID, True)
                            For Each customField As CustomFieldInfo In customFields
                                If _CustomFieldIds.ContainsKey(customField.Name.ToLowerInvariant) Then
                                    _CustomFieldIds(customField.Name.ToLowerInvariant).Add(customField)
                                Else
                                    Dim objList As New List(Of CustomFieldInfo)
                                    objList.Add(customField)
                                    _CustomFieldIds(customField.Name.ToLowerInvariant) = objList
                                End If
                            Next
                        Catch ex As Exception
                            DotNetNuke.Services.Exceptions.Exceptions.LogException(ex)
                        End Try

                    Next
                Else
                    For Each moduleId As Integer In modulesIds
                        customFields = _CustomFieldController.List(moduleId, True)
                        For Each customField As CustomFieldInfo In customFields
                            If _CustomFieldIds.ContainsKey(customField.Name.ToLowerInvariant) Then
                                _CustomFieldIds(customField.Name.ToLowerInvariant).Add(customField)
                            Else
                                Dim objList As New List(Of CustomFieldInfo)
                                objList.Add(customField)
                                _CustomFieldIds(customField.Name.ToLowerInvariant) = objList
                            End If
                        Next
                    Next
                End If

            End If
        End Sub

        Public Function RewriteParams(ByVal groupName As String, ByVal objRewriteType As RewriteType, _
                                       ByVal params As Dictionary(Of UrlParam, String), ByVal behaviour As FriendlierUrlStrategy) As GroupRewriteResult _
            Implements IUrlRewriterProvider.RewriteParams
            Dim toReturn As New GroupRewriteResult()

            If params.Count > 0 Then

                Select Case groupName.ToLowerInvariant
                    Case "displayname"
                        Dim propertyId As Integer = Integer.Parse(params(UrlParam.FromSyntax("propertyid")), CultureInfo.InvariantCulture)
                        toReturn.RewriteValue = GetPropertyDisplayName(propertyId, behaviour)
                        toReturn.ConsumedParameters(UrlParam.FromSyntax("propertyid")) = True
                    Case "papropertytypes"
                        Dim propertyTypeId As Integer = Integer.Parse(params(UrlParam.FromSyntax("propertytypeid")), CultureInfo.InvariantCulture)
                        toReturn.RewriteValue = GetPropertyTypeByPropTypeId(propertyTypeId, behaviour, objRewriteType)
                        toReturn.ConsumedParameters(UrlParam.FromSyntax("propertytypeid")) = True
                    Case "patype"
                        Dim propertyId As Integer = Integer.Parse(params(UrlParam.FromSyntax("propertyid")), CultureInfo.InvariantCulture)
                        toReturn.RewriteValue = GetPropertyTypeByPropId(propertyId, behaviour, objRewriteType)
                        toReturn.ConsumedParameters(UrlParam.FromSyntax("propertyid")) = True

                    Case Else
                        Dim propertyId As Integer = Integer.Parse(params(UrlParam.FromSyntax("propertyid")), CultureInfo.InvariantCulture)

                        If groupName.ToLowerInvariant.StartsWith(glbCustomFieldPrefix.ToLowerInvariant) Then
                            Dim fieldName As String = groupName.Substring(glbCustomFieldPrefix.Length)
                            toReturn.RewriteValue = GetCustomFieldValue(fieldName, propertyId, behaviour)
                            toReturn.ConsumedParameters(UrlParam.FromSyntax("propertyid")) = True
                        ElseIf groupName.ToLowerInvariant.StartsWith(glbAgentProfilePrefix.ToLowerInvariant) Then
                            Dim fieldName As String = groupName.Substring(glbAgentProfilePrefix.Length)
                            Dim uc As New UserController
                            Dim prop As PropertyInfo = _PropertyController.Get(propertyId)
                            Dim agent As UserInfo = uc.GetUser(NukeHelper.PortalId, prop.AuthorID)
                            toReturn.RewriteValue = agent.Profile.GetPropertyValue(fieldName)
                            toReturn.ConsumedParameters(UrlParam.FromSyntax("propertyid")) = True
                        End If
                End Select
            End If
            Return toReturn
        End Function

        Private Function GetPropertyDisplayName(ByVal propertyId As Integer, ByVal behaviour As FriendlierUrlStrategy) As String
            Dim toreturn As String = ""
            Dim prop As PropertyInfo = _PropertyController.Get(propertyId)
            If prop IsNot Nothing AndAlso prop.PropertyID <> -1 Then
                toreturn = prop.DisplayName
            End If
            'Return behaviour.StringEscaper.EscapeString(toreturn)
            Return toreturn
        End Function

        'Private Function GetPropertyType(ByVal propertyId As Integer, ByVal behaviour As FriendlierUrlStrategy) As String
        '    Dim toreturn As String = ""
        '    Dim prop As PropertyInfo = _PropertyController.Get(propertyId)
        '    If prop IsNot Nothing AndAlso prop.PropertyID <> -1 Then
        '        toreturn = prop.PropertyTypeName
        '    End If
        '    Return behaviour.StringEscaper.EscapeString(toreturn)
        'End Function

        Private Function GetPropertyTypeByPropId(ByVal propertyId As Integer, ByVal behaviour As FriendlierUrlStrategy, ByVal objRewriteType As RewriteType) As String

            Dim toReturn As New StringBuilder

            Dim prop As PropertyInfo = _PropertyController.Get(propertyId)
            If objRewriteType = RewriteType.SubPath Then
                Dim propType As PropertyTypeInfo = _PropertyTypeController.Get(prop.ModuleID, prop.PropertyTypeID)
                toReturn.Append(Me.GetPropertyPath(propType, behaviour, objRewriteType))
            Else
                'toReturn.Append(behaviour.StringEscaper.EscapeString(prop.PropertyTypeName))
                toReturn.Append(prop.PropertyTypeName)
            End If

            Return toReturn.ToString

        End Function

        Private Function GetPropertyTypeByPropTypeId(ByVal proptypeID As Integer, ByVal behaviour As FriendlierUrlStrategy, ByVal objRewriteType As RewriteType) As String

            Dim toReturn As New StringBuilder

            Dim propType As PropertyTypeInfo = Me.GetPropertyTypeFromBD(proptypeID)
            If objRewriteType = RewriteType.SubPath Then

                toReturn.Append(Me.GetPropertyPath(propType, behaviour, objRewriteType))
            Else
                'toReturn.Append(behaviour.StringEscaper.EscapeString(propType.Name))
                toReturn.Append(propType.Name)
            End If

            Return toReturn.ToString

        End Function

        Private Function GetPropertyPath(ByVal propType As PropertyTypeInfo, ByVal behaviour As FriendlierUrlStrategy, ByVal objRewriteType As RewriteType) As List(Of String)
            Dim toReturn As List(Of String) = Nothing
            If propType.ParentID > -1 Then
                Dim parentPropType As PropertyTypeInfo = _PropertyTypeController.Get(propType.ModuleID, propType.ParentID)
                toReturn = GetPropertyPath(parentPropType, behaviour, objRewriteType)
            End If
            If toReturn Is Nothing Then
                toReturn = New List(Of String)
            End If
            'toReturn.Append(behaviour.StringEscaper.EscapeString(propType.Name))
            toReturn.Add(propType.Name)
            Return toReturn
        End Function

        Private Function GetPropertyTypeFromBD(ByVal propTypeId As Integer) As PropertyTypeInfo
            Dim toReturn As PropertyTypeInfo

            Dim sqlConn As New SqlConnection(NukeHelper.DnnConnectionString)
            Dim strQuery As New StringBuilder
            strQuery.Append("SELECT * From ")
            strQuery.Append(NukeHelper.DnnDatabaseOwner)
            strQuery.Append(".Ventrian_PropertyAgent_PropertyType")
            strQuery.Append(NukeHelper.DnnObjectQualifier)
            strQuery.Append(" WHERE PropertyTypeID = ")
            strQuery.Append(propTypeId)

            Dim sqlQuery As New SqlCommand(strQuery.ToString)
            sqlConn.Open()
            sqlQuery.Connection = sqlConn
            toReturn = CBO.FillObject(Of PropertyTypeInfo)(sqlQuery.ExecuteReader)
            sqlConn.Close()
            Return toReturn
        End Function

        Private Function GetCustomFieldValue(ByVal fieldName As String, ByVal propertyId As Integer, ByVal behaviour As FriendlierUrlStrategy) As String
            Dim toreturn As String = ""
            Dim prop As PropertyInfo = _PropertyController.Get(propertyId)
            If prop IsNot Nothing AndAlso prop.PropertyID <> -1 Then
                'Dim customFieldId As Integer = _CustomFieldIds(fieldName.ToLowerInvariant).CustomFieldID
                'Dim propValue As PropertyValueInfo= _PropertyValueController.GetByCustomField(propertyId, customFieldId)
                'toreturn = propValue.CustomValue
                For Each item As CustomFieldInfo In _CustomFieldIds(fieldName.ToLowerInvariant)
                    If prop.PropertyList.ContainsKey(item.CustomFieldID) Then
                        toreturn = prop.PropertyList(item.CustomFieldID).ToString
                        Exit For
                    End If
                Next


            End If
            'Return behaviour.StringEscaper.EscapeString(toreturn)
            Return toreturn
        End Function

        Public Function GetCategory(ByVal params As System.Collections.Generic.Dictionary(Of UrlParam, String)) As Integer Implements ICategoryUrlRewriterProvider.GetCategory

            Dim categoryId As Integer = -1

            If params.ContainsKey(UrlParam.FromSyntax("propertyid")) Then
                Dim contentId As Integer = Integer.Parse(params(UrlParam.FromSyntax("propertyid")), CultureInfo.InvariantCulture)
                Dim prop As PropertyInfo = _PropertyController.Get(contentId)

                If prop IsNot Nothing Then
                    Dim ContentCtrl As New ContentController()
                    Dim CatList As List(Of CategoryInfo) = ContentCtrl.GetContentCategories(prop.ModuleID, contentId)
                    If CatList IsNot Nothing AndAlso CatList.Count > 0 Then

                        categoryId = CatList(0).CategoryID
                    End If

                End If

            End If

            Return categoryId

        End Function

        Public ReadOnly Property IsActive As Boolean Implements IIsActive.IsActive
            Get
                'Ventrian.PropertyAgent.PropertyController
                Return DotNetNuke.Framework.Reflection.CreateType("Ventrian.PropertyAgent.PropertyController", True) IsNot Nothing
            End Get
        End Property
    End Class
End Namespace


